package com.googlecode.pathmachine.nn;

/**
 *Name: Neuron
 *
 *Author: John Pendlebury ported to Java from code written by Matt Buckland
 *
 *Description: Represents a Neuron with weighted inputs, a bias and a sigmoid function.
 *
 *You can reuse this code provided you include these comments.
 *I'd also appreciate you letting me know via email just because I'm
 *interested.
 *
 *email: john.pendlebury2@mail.dcu.ie
 */
import java.util.*;

public class Neuron {
    //Storage for the neuron input weights

    private ArrayList<Double> weights;
    private int numInputs;
    //The bias for this neuron
    private double bias;

    //Constructor
    public Neuron(int numInputs) {
        //Remember how many inouts this Neuron has
        this.numInputs = numInputs;

        //Construct a new ArrayList to hold Neuron Inputs
        weights = new ArrayList<Double>(numInputs);

        //Initialise the inputs to random values
        for (int i = 0; i < numInputs; i++) {
            weights.add(Utils.generateRandomClamped());
        }

        //Initialise the bias to a randon value
        bias = Utils.generateRandomClamped();
    }

    public double getOutput(List<Double> inputs) {
        assert inputs.size() == numInputs;

        double netInput = 0;

        for (int k = 0; k < numInputs; k++) {
            netInput += inputs.get(k) * weights.get(k);
        }

        //Add the bias multiplied by minus 1
        netInput += bias * Params.biasFactor;

        //Apply the sigmoid function.
        return applyFunction(netInput, Params.activationResponse);
    }

    public void setWeights(List<Double> weights) {
        assert weights.size() == numInputs + 1;

        int i;

        for (i = 0; i < numInputs; i++) {
            this.weights.set(i, weights.get(i));
        }

        //Set the bias as the last value in the list
        bias = weights.get(i);

    }
    //Applies a sigmoid function to the inputs

    private double applyFunction(double netinput, double response) {
        return (1 / (1 + Math.exp(-netinput / response)));
    }
}
